/**
 * Copyright 2007 American Well Systems
 * All rights reserved.
 *
 * It is illegal to use, reproduce or distribute
 * any part of this Intellectual Property without
 * prior written authorization from American Well.
 */
package org.rich.charlesmurphy.model;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.ddevil.data.BeanData;
import org.ddevil.data.Internal;
import org.rich.charlesmurphy.core.CharliesUtils;
import org.springframework.util.Assert;

/**
 * Essentially a page, and all the resources it requested.
 * @author Rich O'Connell
 */
public class RequestGroup extends BeanData {
private static final long serialVersionUID = -4603521077537038550L;

	private String url;
	private String method;
	private String path;
	private String query;

	private int requests = 0;
	private int success = 0;
	private int cache = 0;
	private int css = 0;
	private int js = 0;
	private int ajax = 0;
	private int images = 0;
	private int other = 0;

	private long totalResponseSize = 0;
	private long totalTime; //elapsed time
	private Date time; // time of first request

	private Request originator;

	@Internal
	private List<Request> children;


	public RequestGroup(Request originator) {
		this.originator = originator;
		url = originator.getUrl();
		path = originator.getPath();
		query = originator.getQuery();
		method = originator.getMethod();

		updateSize(originator);
		time = originator.getStartTime();

		children = new ArrayList<Request>();
	}

	public void addRequest(Request request) {
		if (!children.contains(request)) {
			// sanity check
			Assert.isTrue(getRemoteHost().equals(request.getRemoteHost()),
					"All requests in a request group must be from same remote host. Idiot.");
			children.add(request);

			requests++;
			incrementType(CharliesUtils.determineResourceType(request.getPath()));

			if (CharliesUtils.wasCached(request.getStatus())) {
				cache++;
			}
			else {
				success++;
			}

			updateSize(request);
			// XXX this assumes that each sub request is added in order, from first to last requested
			totalTime = (request.getStartTime().getTime() - originator.getStartTime().getTime())/1000;
		}
	}

	private void incrementType(ResourceType type) {
		switch(type) {
		case AJAX:
			ajax++;
			break;
		case CSS:
			css++;
			break;
		case IMAGE:
			images++;
			break;
		case JS:
			js++;
			break;
		case OTHER:
			other++;
			break;
		}
	}

	private void updateSize(Request record) {
		totalResponseSize += noNulls(record.getResponseBodySize());
	}

	private static long noNulls(Long d) {
		return d != null ? d : 0;
	}

	public String getRemoteHost() {
		return originator.getRemoteHost();
	}

	public List<Request> getChildren() {
		return children;
	}

	/**
	 * @return the url
	 */
	public String getUrl() {
		return url;
	}

	/**
	 * @return the path
	 */
	public String getPath() {
		return path;
	}

	/**
	 * @return the method
	 */
	public String getMethod() {
		return method;
	}

	/**
	 * @return the originator
	 */
	public Request getOriginator() {
		return originator;
	}

	/**
	 * @return the query
	 */
	public String getQuery() {
		return query;
	}

	/**
	 * @return the requests
	 */
	public int getRequests() {
		return requests;
	}

	/**
	 * @return the success
	 */
	public int getSuccess() {
		return success;
	}

	/**
	 * @return the cache
	 */
	public int getCache() {
		return cache;
	}

	/**
	 * @return the css
	 */
	public int getCss() {
		return css;
	}

	/**
	 * @return the js
	 */
	public int getJs() {
		return js;
	}

	/**
	 * @return the ajax
	 */
	public int getAjax() {
		return ajax;
	}

	/**
	 * @return the images
	 */
	public int getImages() {
		return images;
	}

	/**
	 * @return the other
	 */
	public int getOther() {
		return other;
	}

	/**
	 * @return the time
	 */
	public Date getTime() {
		return time;
	}

	/**
	 * @return the totalTime
	 */
	public Long getTotalTime() {
		return totalTime;
	}

	/**
	 * An aggregate of the response body sizes for all requests in this group.
	 * @return the responseSize
	 */
	public Long getTotalResponseSize() {
		return totalResponseSize;
	}

}
